import { recursiveIterate } from '@ibiz-template/core';
import {
  ControlController,
  IToolbarEvent,
  UIActionButtonState,
  ControlVO,
  IToolbarController,
  UIActionUtil,
  IToolbarState,
  ButtonContainerState,
  ViewMode,
  IExtraButton,
} from '@ibiz-template/runtime';
import {
  IDEToolbar,
  IDEToolbarItem,
  IDETBUIActionItem,
} from '@ibiz/model-core';

/**
 * 工具栏控制器
 * @author lxm
 * @date 2023-03-28 06:44:26
 * @export
 * @class ToolbarController
 * @extends {ControlController<ToolbarModel>}
 */
export class ToolbarController
  extends ControlController<IDEToolbar, IToolbarState, IToolbarEvent>
  implements IToolbarController
{
  protected initState(): void {
    super.initState();
    this.state.buttonsState = new ButtonContainerState();
    this.state.viewMode = ViewMode.EMBED;
    this.state.extraButtons = {};
  }

  /**
   * 执行按钮的界面行为（如果按钮存在界面行为的话）
   *
   * @author zk
   * @date 2023-07-20 10:07:22
   * @protected
   * @param {IDEToolbarItem} item 工具栏项
   * @param {MouseEvent} event 鼠标事件
   * @param {IData} [param] 界面行为参数（界面行为点击自定义按钮可能需要传参数到行为去，标准行为忽略此参数）
   * @return {*}  {Promise<void>}
   * @memberof ToolbarController
   */
  protected async doUIAction(
    item: IDEToolbarItem,
    event: MouseEvent,
    param: IData = {},
  ): Promise<void> {
    // 执行界面行为
    if (item.itemType === 'DEUIACTION') {
      const actionId = (item as IDETBUIActionItem).uiactionId;
      const res = await this.ctx.view.call('GetData');
      const data = res || [];
      const args = this.getEventArgs();
      args.params = Object.assign(param, args.params);
      await UIActionUtil.execAndResolved(actionId!, {
        ...args,
        data,
        event,
      });
    }
  }

  protected async onCreated(): Promise<void> {
    super.onCreated();

    this.state.viewMode = this.ctx.view.modal.mode;

    // 初始化工具栏状态控制对象
    recursiveIterate(
      this.model,
      (item: IDEToolbarItem) => {
        if (item.itemType === 'DEUIACTION') {
          const uiItem = item as IDETBUIActionItem;
          const buttonState = new UIActionButtonState(
            uiItem.id!,
            this.context.srfappid!,
            uiItem.uiactionId!,
          );

          this.state.buttonsState.addState(uiItem.id!, buttonState);
        }
      },
      { childrenFields: ['detoolbarItems'] },
    );
    await this.state.buttonsState.update();
  }

  /**
   *
   * @author lxm
   * @date 2023-03-28 07:10:55
   * @param {IPSDEToolbarItem} item
   * @param {MouseEvent} event
   * @return {*}  {Promise<void>}
   */

  /**
   * 工具栏按钮点击事件
   *
   * @author zk
   * @date 2023-07-20 03:07:29
   * @param {(IDEToolbarItem | IExtraButton)} item
   * @param {MouseEvent} event
   * @param {IData} [params] 界面行为参数（界面行为点击自定义按钮可能需要传参数到行为去，标准行为忽略此参数）
   * @return {*}  {Promise<void>}
   * @memberof ToolbarController
   */
  async onItemClick(
    item: IDEToolbarItem | IExtraButton,
    event: MouseEvent,
    params?: IData,
  ): Promise<void> {
    this.state.buttonsState.setLoading(item.id!);
    const isExtra = (item as IExtraButton).buttonType === 'extra';
    try {
      await this.evt.emit('onClick', {
        event,
        eventArg: item.id!,
        buttonType: isExtra ? 'extra' : 'deuiaction',
      });

      // 工具栏才走界面行为
      if (!isExtra) {
        await this.doUIAction(item, event, params);
      }
    } finally {
      this.state.buttonsState.setLoading('');
    }
  }

  calcButtonState(data?: IData, appDeId?: string): void {
    let _data = data;
    if (data && data instanceof ControlVO) {
      _data = data.getOrigin();
    }
    this.state.buttonsState.update(_data, appDeId);
  }

  setExtraButtons(
    position: 'before' | 'after' | number,
    buttons: IExtraButton[],
  ): void {
    if (!this.state.extraButtons[position]) {
      this.state.extraButtons[position] = [];
    }
    this.state.extraButtons[position].push(...buttons);
  }

  clearExtraButtons(position?: 'before' | 'after' | number): void {
    // 清空所有
    if (position === undefined) {
      this.state.extraButtons = {};
    } else {
      this.state.extraButtons[position] = [];
    }
  }
}
